package gbench.appdemo.myworld.market.trading;

import java.time.LocalDateTime;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;

import gbench.appdemo.myworld.market.SimpleMarket;
import gbench.appdemo.myworld.market.SimpleMarket.DRCR;
import gbench.appdemo.myworld.market.commodity.Commodity;
import gbench.appdemo.myworld.market.license.CommodityLicense;
import gbench.appdemo.myworld.market.store.OnlineStore;
import gbench.common.tree.LittleTree.IRecord;
import static gbench.common.tree.LittleTree.IRecord.*;

/**
 * 交易经纪
 * @author gbench
 *
 */
public class TradeBroker extends TradeProxy<TradeBroker>{

    /**
     * 
     * @param participantId
     * @param licenses
     */
    public TradeBroker(String participantId, Map<String, CommodityLicense<Commodity, Commodity>> licenses) {
        super(participantId, licenses);
    }
    
    /**
     * 
     * @param proxy
     */
    public TradeBroker(TradeProxy<?> proxy) {
        super(proxy.currentParticipant, proxy.getLicenses());
    }
    
    /**
     * 根据 commodity查找 对应类型的交易许可
     * @param commodity 商品对象
     * @return 查找交易许可
     */
    public Stream<CommodityLicense<Commodity,Commodity>> getProviders(Commodity commodity){
        return this.getLicenses().values().stream().filter(e->e.getCommodity().equals(commodity));
    }
    
    /**
     * 根据 commodity查找 对应类型的交易许可
     * @param commodity 商品对象
     * @return 查找交易许可
     */
    public Optional<CommodityLicense<Commodity,Commodity>> getAnyProvider(Commodity commodity){
        return this.getLicenses().values().stream().filter(e->e.getCommodity().equals(commodity)).findAny();
    }
    
    /**
     * 根据 commodity查找 对应类型的交易许可
     * @param commodity 商品对象
     * @return 查找交易许可
     */
    public Stream<OnlineStore> getProviderStore(Commodity commodity){
        return this.getLicenses().values().stream().filter(e->e.getCommodity().equals(commodity)).map(e->e.getOwner());
    }
    
    /**
     * 
     * @param drcr partA 与 partB 的借贷方向 DR：表示 正序 partA,partB,CR 表示 partB,partA
     * @param commodity 商品对象
     * @param filter 过滤器
     * @param cs 回调处理函数
     * @return 实例本身以实现链式编程。
     */
    public TradeBroker withTransaction(final DRCR drcr,final Commodity commodity,
        Predicate<CommodityLicense<Commodity,Commodity>> filter,
        Consumer<SimpleMarket<Commodity>.TradeTransaction<Commodity, Commodity>> cs) {
        final var opt = this.getProviders(commodity).filter(filter).findAny();
        opt.ifPresent(partB->{
            partB.getMarket().withTransaction(drcr,trans->{
                trans.setPartA(this.getCurrent());
                trans.setPartB(partB);
                cs.accept(trans);
            });// partB
        });
        
        return this;
    }
    
    /**
     * 支付na单位的 当前的用户的产品 换取  nb单位的 commodity 
     * @param commodity
     * @param na 支付 na 单位
     * @param nb nb单位的 commodity
     * @return SimpleStore
     */
    public  TradeBroker purchase(final Commodity b,final Number nb,final Number na ) {
        this.withTransaction(DRCR.CR, b, e->true,trans->{
            trans.setPrice(this.getCurrent().getCommodity(), na,b, nb);
            final var partB = trans.getPartB();
            final var onlineStore = partB.getOwner();
            final var commodity = partB.getCommodity();
            if(onlineStore.getQuotation(commodity)==null) {// 随机初始化一个价格
                onlineStore.initializeQuotation(commodity,trans.getPrice());
            }
            onlineStore.freeze(this,commodity, nb);
            System.out.println(onlineStore);
            onlineStore.trialBalance(commodity).forEach(System.out::println);
            //onlineStore.getTransactions(commodity).forEach(System.out::println);
        });// withTransaction
        
        return this;
    }
    
    /**
     * 支付na单位的 当前的用户的产品 换取  nb单位的 commodity 
     * @param commodity
     * @param na 支付 na 单位
     * @param nb nb单位的 commodity
     * @return SimpleStore
     */
    public  TradeBroker purchase(final CommodityLicense<Commodity,Commodity>license,final Commodity b,final Number nb,final Number na ) {
        this.withTransaction(DRCR.CR, b, e->e.equals(license),trans->{
            trans.setPrice(this.getCurrent().getCommodity(), na,b, nb);
            final var partB = trans.getPartB();
            final var onlineStore = partB.getOwner();
            final var commodity = partB.getCommodity();
            if(onlineStore.getQuotation(commodity)==null) {// 随机初始化一个价格
                onlineStore.initializeQuotation(commodity,trans.getPrice());
            }
            onlineStore.freeze(this,commodity, nb);
            System.out.println(onlineStore);
        });// withTransaction
        
        return this;
    }
    
    /**
     * 冻结店铺的partB 商品 
     * @param partB
     * @param b
     * @param nb
     * @return
     */
    public TradeBroker freeze(final CommodityLicense<Commodity,Commodity>partB,final Commodity b,final Number nb) {
        partB.getOwner().freeze(this,b, nb);
        taskTodos.add(REC("type","freezed","license",partB,"commodity",b,"quantity",nb,"timeout",0,"time",LocalDateTime.now()));
        return this;
    }
    
    /**
     * 冻结店铺的partB 商品 
     * @param partB
     * @param b
     * @param nb
     * @return
     */
    public TradeBroker freeze(final CommodityLicense<Commodity,Commodity>partB,final Commodity b,final Number nb,final Number timeout) {
        partB.getOwner().freeze(this,b, nb,timeout);
        taskTodos.add(REC("type","freezed","license",partB,"commodity",b,"quantity",nb,"timeout",timeout,"time",LocalDateTime.now()));
        return this;
    }
    
    public List<IRecord> taskTodos = new LinkedList<>();// 待完成事项。
}
